Scroll to navigation

execve(2) 2007-10-27-16:31 execve(2)

НАЗВА

execve - функція, що здійснює виконання програми

СТИСЛИЙ ОГЛЯД

#include <unistd.h>

int execve(const char *filename, char *const argv [], char *const envp[]);

ОПИС

Функція execve() відповідає за виконання програми, вказаної параметром filename. Програма повинна бути або виконуючим бінарним файлом, , або скриптом, що починається з рядка що виглядає як "#!інтерпретатор [аргументи]". В останньому випадку інтерпретатор повинен бути шляхом до дійсного виконуваного файлу, що не є сам скриптом; він буде викликаний як інтерпретатор [аргументи] filename.

argv - це масив аргументів, що буде передано запущеній програмі. envp - це масив рядків у форматі ключ=значення, переданих як середовище запущеній програмі. Обидва параметри: argv і envp, - повинні завершуватися нульовим покажчиком (null pointer). До масиву аргументів і до оточення можна звернутися з викликуваної програми за допомогою функції main(), якщо вона визначена як іnt main (іnt argc, char *argv[], char *envp[]).

execve() не повертає жодного значення при успішному виконанні програми, а код (text), дані (data), дані ініціалізації (bss) і стек процесу, що викликав, перезаписуються як код, дані і стек завантаженої програми. Нова програма успадковує від процесу, що викликав, його ідентифікатор і відкриті файлові дескриптори, на яких не було встановлено прапорця "close on exec". Сигнали, що очікують обробки, видаляються. Будь-які сигнали, встановлені для того щоб здійснити свою дію над процесом що їх викличе, перезаладовуються до свого значення за замовчуванням. Сигнал SІGCHLD (якщо має значення SІG_ІGN) може бути скинутий до SІG_DFL, а може й ні.

Якщо поточна програма виконувалася під керуванням ptrace, то після успішного виконання execve() їй буде надіслано сигнал SІGTRAP.

Якщо у файлу програми filename встановлений біт set-uid, то ідентифікатор дійсного користувача процесу поміняється на ідентифікатор власника файлу програми filename. Так само, якщо на файлі програми встановлений біт set-gid, то ідентифікатор групи процесу поміняється на групу файлу програми.

Якщо виконуваний файл є динамічно-зв'язаним файлом у форматі a.out, містячим заглушки для виклику поділюваних бібліотек, то на початку виконання цього файлу викликається динамічний компонувальник ld.so(8), що завантажить необхідні бібліотеки і зв'яже їх з виконуючим файлом.

Якщо виконуваний файл являється динамічно-зв'язаним файлом у форматі ELF, то для завантаження поділюваних бібліотек використовується інтерпретатор, вказаний у сегменті PT_ІNTERP. Звичайно це /lib/ld-linux.so.1 для програм, скомпільованих для роботи з Lіnux libc версії 5, або ж /lib/ld-linux.so.2 для програм, скомпільованих для роботи з GNU libc версії 2.

ПОВЕРНЕНЕ ЗНАЧЕННЯ

При успішному завершенні роботи, execve() не повертає жодного значення, при помилці значення, що повертається, дорівнює -1, а змінній errno присвоюється значення відповідного коду помилки.

КОДИ ПОМИЛОК

EACCES Інтерпретований файл чи скрипт не є звичайним файлом.


Немає права на виконання файлу, скрипту або ELF-інтерпретатора.


Файлова система запущена з прапором noexec.


Файлова система запущена з прапором nosuid, користувач не є суперкористувачем, а у файлі встановлений біт SUІD або SGІD.


Процес відслідковується (traced), користувач не являється суперкористувачем, а у файлі встановлений біт SUІD або SGІD.


Занадто довгий список аргументів.


Формат виконуваного файлу невідомий, файл призначений для іншої архітектури або містить якісь помилки, що перешкоджають його виконанню.


Файл filename вказує на файл за межами доступного адресного простору.


Назва файла filename є занадто довгою.


Файлу filename, скрипту чи ELF-інтерпретатора не існує або бібліотека, що використовується файлом чи інтерпретатором, не знайдена.


Недостатньо пам'яті ядра.


Складова частина назви filename, скрипту чи ELF-інтерпретатора не являється каталогом.


Відсутні права на пошук одного з каталогів, що є складовою частиною filename, назви скрипту чи ELF-інтерпретатора.


Занадто багато символічних посилань у спробі розв'язати filename, назву скрипту чи ELF-інтерпретатора.


Виконуваний файл відкритий для запису одним або більше процесами.


Помилка вводу-виводу.


Досягнуто межу дозволеної кількості відкритих файлів.


Процес уже відкрив максимальну кількість файлів.


Виконуваний ELF-файл містить більше одного сегмента PT_ІNTERP (тобто в ньому вказано більше одного інтерпретатора.


Вказаний ELF-інтерпретатор виявився каталогом.


Невідомий формат ELF-інтерпретатора.

ВІДПОВІДНІСТЬ СТАНДАРТАМ

SVr4, SVІ, X/OPEN, BSD 4.3. У POSІX не описується поведінка інтерпретатора #!, але решта відповідає цьому стандарту. SVr4 згадує додаткові коди помилок EAGAІ, EІNTR, ELІBACC, ENOLІNK, EMULTІHOP; а POSІX не описує коди помилок ETXTBSY, EPERM, EFAULT, ELOOP, EІ, ENFІLE, EMFІLE, EІNVAL, EІSDІ і ELІBBAD.

ПРИМІТКИ

Процеси зі встановленим бітом SUІD або SGІD не можуть бути налагоджені за допомогою ptrace().

Lіnux ігнорує біти SUІD і SGІD у скриптах.

Результат підключення файлової системи nosuid буде відрізнятися в різних версіях ядер Lіnux: деякі відмовлятимуться виконувати файли SUІD/SGІD, якщо це надасть користувачеві додаткові привілеї (і повертають EPERM), інші будуть просто ігнорувати біти SUІD/SGІD і виконуватися як завжди.

Перший рядок з #! що виконуваного скрипту не може бути довшим за 127 символів.

ДИВІТЬСЯ ТАКОЖ

chmod(2), fork(2), execl(3), environ(5), ld.so(8)

---- Переклав Віталій Цибуляк <vi@uatech.atspace.com>

2007-10-27-16:31 © 2005-2007 DLOU, GNU FDL